package com.xiaode.common;

import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jfinal.core.Controller;
import com.jfinal.core.Path;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.xiaode.common.anotation.Authority;
import com.xiaode.common.constant.Const;
import com.xiaode.common.model.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.time.ZoneOffset;
import java.util.*;


public class SysInit {

    public static final Map<Integer, Integer> stateMap = new HashMap<Integer, Integer>();

    static {
        //初始化stateMap 对应重要他人不同状态 对用的优先级  key 重要他人/任务状态 value 代表优先级 1最大 5最小
        stateMap.put(3, 1);
        stateMap.put(1, 2);
        stateMap.put(2, 3);
        stateMap.put(5, 4);
        stateMap.put(4, 5);
    }

    //常量类型1.周期2.任务类型3.班级4.年级5.版本
    public void init() {
        Cache redis = Redis.use();
        //密保问题
        List<SecurityQuestionConstant> securityQuestionConstantList = SecurityQuestionConstant.dao.findAll();
        for(SecurityQuestionConstant securityQuestionConstant : securityQuestionConstantList) {
        	redis.set(Const.SecretProtection.problem + securityQuestionConstant.getId(), securityQuestionConstant.getQuestion());
        }
        //把学生信息存入redis
        updateStudent(redis);
        System.err.println("| 初始化redis学生信息完成");
        //把教师信息存入redis
        updateTeacher(redis);
        System.err.println("| 初始化redis老师信息完成");
        //保存url匹配路径与权限
        getMyPermission();
        System.err.println("| 初始化url匹配路径与权限完成");
        //添加群聊
//        initGroupRel();
        System.err.println("| 初始化聊天群完成");
        //初始化accountId信息
        initUserAcoountId();
        System.err.println("| 初始化accountId信息");

    }

    /**
     * 初始化accountId信息
     */
    private void initUserAcoountId() {
        Cache redis = Redis.use();
        List<Record> stuRecords = Db.find("SELECT id,user_type userType,accountId,name,avatarUrl,sex FROM student WHERE accountId IS NOT NULL AND isDele = 0");
        List<Record> adRecords = Db.find("SELECT id,user_type userType,accountId,name,avatarUrl,1 sex FROM admin WHERE accountId IS NOT NULL AND isDele = 0");
        List<Record> parRecords = Db.find("SELECT id,user_type userType,accountId,name,wxAvatar avatarUrl,gender sex FROM parent WHERE accountId IS NOT NULL AND isDelete = 0");
        List<Record> externalRecords = Db.find("SELECT id,user_type userType,accountId,name,avatarUrl avatarUrl FROM external WHERE accountId IS NOT NULL AND isDele = 0");
        stuRecords.addAll(adRecords);
        stuRecords.addAll(parRecords);
        stuRecords.addAll(externalRecords);
        stuRecords.forEach(record -> redis.hset(Const.user.AccountIdInfo , record.getInt("accountId"),record));
    }

    /**
     * 比较状态得出正确的sumState
     */
    public static int getSumState(Integer curState, Integer state) {
        if (curState == null){
            return state;
        }
        return stateMap.get(curState) < stateMap.get(state) ? curState : state;
    }

    /**
     * 初始化群聊
     */
    public static void initGroupRel() {
        Prop use = PropKit.use("server.properties");
        HashMap<String, Object> paramMap = new HashMap<>();
        List<Record> groupUserList = Db.find("SELECT accountId,chatGroupId FROM chat_group_user");
        int[][] arr = new int[groupUserList.size()][2];
        int i = 0;
        for (Record groupUser : groupUserList) {
        	if(groupUser.getInt("accountId") != null && groupUser.getInt("chatGroupId") != null) {
        		arr[i++] = new int[]{groupUser.getInt("accountId"),groupUser.getInt("chatGroupId")};
        	}
        }
        String s2 = JSONUtil.toJsonStr(arr);
        paramMap.put("jsonGroups",s2);
        try {
        	int count = 0;
        	String response;
            do {
                response = HttpRequest.post(use.get("chat.ip") + "/imSys/initGroups")
                        .header("serviceId", use.get("chat.serviceId"))
                        .header("accessKey", use.get("chat.accessKey"))
                        .header("secretKey", use.get("chat.secretKey"))
                        .header("dense", use.get("chat.dense")).form(paramMap).execute().body();
            } while (!JSONUtil.parseObj(response).getStr("state").equals("ok") && ++count <= 3);
        } catch (Exception e) {
        	e.printStackTrace();
            System.out.println("初始化教师全校群聊失败");
        }
    }

	/**
	 * 把学生信息存入redis
	 */
    public static void updateStudent(Cache redis) {
        //把学生信息存入redis
        List<Student> students = Student.dao.find("SELECT id,name,studentNo,accountId,number,avatarUrl,zScore,sex,grade,clasId,schoolYear,state,isMainland,lastLoginTime,isDele FROM student where isDele = 0");
        for (int i = 0; i < students.size(); i++) {
            Student student = students.get(i);
            Double zscore = redis.zscore(Const.user.lastLoginTimeS, student.getId());
            if (zscore == null) {
                student.put("lastLoginTimestamp", student.getLastLoginTime() == null ? 0 : student.getLastLoginTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            } else {
                student.put("lastLoginTimestamp", zscore);
            }
            Record record = Db.findFirst("SELECT ad.id,ad.name FROM student stu INNER JOIN teacher_student ts ON stu.id = ts.studentId INNER JOIN admin ad on ad.id = ts.teacherId WHERE stu.id = ? AND ts.state = 2", student.getId());
            if (record != null) {
                student.put("teacherId", record.getInt("id"));
                student.put("teacher", record.getStr("name"));
            } else {
                student.put("teacher", null);
                student.put("teacherId", null);
            }
            List<Record> recordList = Db.find("SELECT par.wxNickname FROM student stu INNER JOIN parent_student ps ON stu.id = ps.studentId INNER JOIN parent par ON par.id = ps.parentId WHERE stu.id = ? AND ps.state = 2", student.getId());
            student.put("parent", recordList);
            Record example = Db.findFirst("SELECT ex.id,ex.name FROM student stu INNER JOIN `example` ex ON stu.id = ex.studentId WHERE stu.id = ? AND ex.isDele = 0", student.getId());
            if (example != null) {
                student.put("example", example.getStr("name"));
            }
        }
        for (int i = 0; i < students.size(); i++) {
            Student student = students.get(i);
            redis.set(Const.user.Student + student.getId(), student);
            redis.zadd(Const.user.StudentScore, student.getZScore(), student.getId());
        }
    }

    /**
     * 把教师信息存入redis
     */
    public static void updateTeacher(Cache redis) {

        List<Admin> admins = Admin.dao.find("SELECT * from admin where isDele = 0");
        for (Admin admin : admins) {
            Double zscore = redis.zscore(Const.user.lastLoginTimeT, admin.getId());
            if (zscore == null || zscore == 0) {
                redis.zadd(Const.user.lastLoginTimeT, admin.getLastLoginTime() == null ? 0 : admin.getLastLoginTime().toInstant(ZoneOffset.of("+8")).toEpochMilli(), admin.getId());
                admin.put("timeStamp", admin.getLastLoginTime() == null ? 0 : admin.getLastLoginTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            } else {
                admin.put("timeStamp", zscore.longValue());
            }
        }
        admins.forEach(admin -> redis.set(Const.user.Admin + admin.getId(), admin));
    }
    
    /**
     * 把外部信息存入redis
     */
    public static void updateExternal(Cache redis) {

        List<External> externalList = External.dao.find("SELECT * from external where isDele = 0");
        for (External external : externalList) {
            Double zscore = redis.zscore(Const.user.lastLoginTimeE, external.getId());
            if (zscore == null || zscore == 0) {
                redis.zadd(Const.user.lastLoginTimeE, external.getLastLoginTime() == null ? 0 : external.getLastLoginTime().toInstant(ZoneOffset.of("+8")).toEpochMilli(), external.getId());
                external.put("timeStamp", external.getLastLoginTime() == null ? 0 : external.getLastLoginTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            } else {
            	external.put("timeStamp", zscore.longValue());
            }
        }
        externalList.forEach(external -> redis.set(Const.user.External + external.getId(), external));
    }

    /**
     * 获得我的权限点
     */
    public void getMyPermission() {
        HashMap<String, Map<String, String>> pathMethodMap = new HashMap<>();
        Map<String, Map<Integer, List<String>>> permissionMap = new HashMap<>();
        Set<Class<?>> controllerClasses = ClassScanner.scanPackage("com.xiaode.controller.admin", aClass -> Controller.class.isAssignableFrom(aClass));
        if (controllerClasses.isEmpty()) {
            return;
        }
        for (Class<?> controllerClass : controllerClasses) {
            List<Method> methods = ReflectUtil.getPublicMethods(controllerClass,
                    method -> method.getAnnotation(Authority.class) != null && Modifier.isPublic(method.getModifiers()));
            //解析类上注解
            Path path = controllerClass.getAnnotation(Path.class);
            if (path == null) {
                continue;
            }
            //访问路径
            String pathValue = path.value();
            HashMap<String, String> methodMap = new HashMap<>();

            for (Method method : methods) {
                //获取方法名称
                String name = method.getName();

                Authority annotation = method.getAnnotation(Authority.class);
                String description = annotation.description();
                String s = annotation.permissionName();
                int type = annotation.type();
                methodMap.put(name, s + ":" + description + ":" + type);
                Map<Integer, List<String>> listMap = permissionMap.get(s);
                if (listMap == null) {
                    HashMap<Integer, List<String>> childMap = new HashMap<>();
                    childMap.put(1, new ArrayList<>());
                    childMap.put(2, new ArrayList<>());
                    List<String> strings = childMap.get(type);
                    strings.add(annotation.permission());
                    permissionMap.put(s, childMap);
                } else {
                    List<String> strings = listMap.get(type);
                    strings.add(annotation.permission());
                }
            }

            //存入map
            pathMethodMap.put(pathValue, methodMap);
        }

        Cache redis = Redis.use();
        redis.set("readEditPermissionMap", permissionMap);
        redis.set("pathMethodMap", pathMethodMap);

        //删除权限
        Db.update("TRUNCATE authority_permission");
        //保存权限
        Set<String> keySet = permissionMap.keySet();
        Iterator<String> iterator = keySet.iterator();
        ArrayList<com.xiaode.common.model.Authority> authorities = new ArrayList<>();
        while (iterator.hasNext()) {
            String next = iterator.next();
            //查询当前权限是否已经存在
            com.xiaode.common.model.Authority first = com.xiaode.common.model.Authority.dao.findFirst("SELECT id from authority WHERE name = ?", next);
            if (first != null) {
                continue;
            }
            com.xiaode.common.model.Authority authority = new com.xiaode.common.model.Authority();
            authority.setName(next);
            authorities.add(authority);
        }
        //批量保存
        Db.batchSave(authorities, authorities.size());

        //保存Authority与permission之间关系
        Set<Map.Entry<String, Map<Integer, List<String>>>> keyValueSet = permissionMap.entrySet();
        Iterator<Map.Entry<String, Map<Integer, List<String>>>> kvIterator = keyValueSet.iterator();
        ArrayList<AuthorityPermission> authorityPermissions = new ArrayList<>();
        while (kvIterator.hasNext()) {
            Map.Entry<String, Map<Integer, List<String>>> next = kvIterator.next();
            String key = next.getKey();
            com.xiaode.common.model.Authority authority = com.xiaode.common.model.Authority.dao.findFirst("SELECT * FROM authority WHERE name = ?", key);
            Map<Integer, List<String>> value = next.getValue();
            List<String> readPermissionList = value.get(1);
            for (String readPermission : readPermissionList) {
                AuthorityPermission authorityPermission = new AuthorityPermission();
                authorityPermission.setAuthorityId(authority.getId());
                authorityPermission.setReadOnly(1);
                authorityPermission.setPermission(readPermission);
                authorityPermissions.add(authorityPermission);
            }
            List<String> writePermissionList = value.get(2);
            for (String writePermission : writePermissionList) {
                AuthorityPermission authorityPermission = new AuthorityPermission();
                authorityPermission.setAuthorityId(authority.getId());
                authorityPermission.setReadOnly(2);
                authorityPermission.setPermission(writePermission);
                authorityPermissions.add(authorityPermission);
            }
        }
        Db.batchSave(authorityPermissions, authorityPermissions.size());

    }

    /**
     * 初始化好友
     */
    public static void initFriends() {
        List<TeacherStudent> studentList = TeacherStudent.dao.find("SELECT * FROM teacher_student WHERE state = 2 AND isFriend = 0");
        HashMap<String, Object> requestMap = new HashMap<>();
        ArrayList<int[]> ints = new ArrayList<>();
        String state = "";
        for (TeacherStudent teacherStudent : studentList) {
            int[] ints1 = new int[2];
            ints1[0] = teacherStudent.getTeacherId();
            ints1[1] = teacherStudent.getStudentId();
            ints.add(ints1);
        }
        String s = JSONUtil.toJsonStr(ints);
        Prop use = PropKit.use("server.properties");
        requestMap.put("jsonFriends", s);
        //发送教师添加学生请求
        int i = 0;
        try {
            do {
                String res = HttpRequest.post(use.get("chat.ip") + "/imSys/initFriends")
                        .header("serviceId", use.get("chat.serviceId"))
                        .header("accessKey", use.get("chat.accessKey"))
                        .header("secretKey", use.get("chat.secretKey"))
                        .header("dense", use.get("chat.dense")).form(requestMap).execute().body();
                JSONObject jsonObject = JSONUtil.parseObj(res);
                state = jsonObject.getStr("state");
                if (!state.equals("ok")) {
                    i++;
                }
            } while (!state.equals("ok") && i <= 3);
        } catch (Exception e) {

        }
        //如果i < 3 代表 添加好友成功  更新数据库库添加好友状态
        if (i < 3) {
            Db.update("UPDATE teacher_student set isFriend = 1 WHERE state = 2");
        }

    }

}
